package com.fengmi.miaosha.service.impl;

import cn.hutool.json.JSONUtil;
import com.fengmi.interceptor.UserInfoInterceptor;
import com.fengmi.miaosha.entity.MsGoods;
import com.fengmi.miaosha.entity.MsOrder;
import com.fengmi.miaosha.mapper.MsOrderMapper;
import com.fengmi.miaosha.service.IMsOrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fengmi.vo.ResultVO;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.redisson.client.RedisClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author zhuxm
 * @since 2022-03-17
 */
@Service
public class MsOrderServiceImpl extends ServiceImpl<MsOrderMapper, MsOrder> implements IMsOrderService {

    @Autowired
    private StringRedisTemplate redisTemplate;
//
//    @Override
//    public ResultVO msOrder(String goodsId, String time) {
//
//
//
//        //获取锁
//        Boolean hasLock = redisTemplate.boundValueOps("menhu:miaosha:lock"+goodsId).setIfAbsent("1");//setnx  menhu:miaosha:lock 1
//
//        if(!hasLock){  //非阻塞锁
//            return  new ResultVO(false,"系统繁忙，请稍后重试!!!");
//        }
//        //设置过期时间
//        redisTemplate.expire("menhu:miaosha:lock"+goodsId,10, TimeUnit.SECONDS);
////        while (!hasLock){ //阻塞式锁
////            hasLock = redisTemplate.boundValueOps("menhu:miaosha:lock"+goodsId).setIfAbsent("1");
////            try {
////                Thread.sleep(800);
////            } catch (InterruptedException e) {
////                e.printStackTrace();
////            }
////        }
//
//
//
//        BoundHashOperations<String, Object, Object> operations = redisTemplate.boundHashOps("menhu:miaosha:goods");
//
//        BoundHashOperations<String, Object, Object> orderOpt = redisTemplate.boundHashOps("menhu:miaosha:order:" + goodsId);
//
//
//        Object goodsListJson = operations.get(time);
//
//        if(StringUtils.isEmpty(goodsListJson)){
//
//            return  new ResultVO(false,"活动已经结束");
//        }
//
//        List<MsGoods> msGoods = JSONUtil.toList((String) goodsListJson, MsGoods.class);
//
//        List<MsGoods> goodsList = msGoods.stream().filter(goods -> goodsId.equals(goods.getSeckillId()+"")).collect(Collectors.toList());
//
//        MsGoods goodsInfo = goodsList.get(0);
//
//        Integer seckillRemaining = goodsInfo.getSeckillRemaining();
//
//        if (seckillRemaining < 1) {//1  1
//            return  new ResultVO(false,"该商品已经卖完");
//        }
//
//
//        //判断用户是否已经购买了该商品
//        String userId = UUID.randomUUID().toString();  //UserInfoInterceptor.getUserInfo().getUserId();
//        Object orderJson = orderOpt.get(userId);
//
//        if(!StringUtils.isEmpty(orderJson)){
//            return  new ResultVO(false,"不要重复下单");
//        }
//
//
//        //下单
//        MsOrder msOrder = new MsOrder();
//        msOrder.setSeckillUserId(userId);
//        msOrder.setCreatedate(new Date());
//        msOrder.setSeckillMoney(goodsInfo.getSeckillPrice());
//        msOrder.setUpdatedate(new Date());
//        msOrder.setSeckillGoodsId(goodsInfo.getSeckillId()+"");
//
//        orderOpt.put(userId,JSONUtil.toJsonStr(msOrder));
//
//        try {
//            Thread.sleep(2000);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//
//        //扣库存
//        for (MsGoods msGood : msGoods) {
//            if(goodsId.equals(msGood.getSeckillId()+"")){
//                msGood.setSeckillRemaining(goodsInfo.getSeckillRemaining() - 1);
//            }
//        }
//        operations.put(time,JSONUtil.toJsonStr(msGoods));
//
//
//
//        //释放锁
//        redisTemplate.delete("menhu:miaosha:lock"+goodsId);
//
//
//        return new ResultVO(true,"success");
//    }



//    @Override
//    public ResultVO msOrder(String goodsId, String time) {
//
//        try {
//            //获非阻塞取锁 setnx lock 1
//            Boolean hasLock = redisTemplate.boundValueOps("menhu:miaosha:lock:"+goodsId).setIfAbsent("1");
//            if(!hasLock){
//                return new ResultVO(false,"获取锁失败");
//            }
//
//            //设置过期时间
//            //redisTemplate.expire("menhu:miaosha:lock:"+goodsId,1,TimeUnit.SECONDS)
////            获取阻塞锁
////            Boolean hasLock =false;
////            while (!hasLock){
////                hasLock = redisTemplate.boundValueOps("menhu:miaosha:lock").setIfAbsent("1");
////            }
//
//            BoundHashOperations<String, Object, Object> operations = redisTemplate.boundHashOps("menhu:miaosha:goods:"+time);
//
//            BoundHashOperations<String, Object, Object> orderOpt = redisTemplate.boundHashOps("menhu:miaosha:order:" + goodsId);
//
//
//            Object goodsJson = operations.get(goodsId);
//
//            if(StringUtils.isEmpty(goodsJson)){
//
//                return  new ResultVO(false,"活动已经结束");
//            }
//
//            MsGoods msGoods = JSONUtil.toBean((String) goodsJson, MsGoods.class);
//
//            Integer seckillRemaining = msGoods.getSeckillRemaining();  //5
//
//            if (seckillRemaining < 1) {//1  1
//
//                return  new ResultVO(false,"该商品已经卖完");
//            }
//
//
//            //判断用户是否已经购买了该商品
//            String userId = UUID.randomUUID().toString();  //UserInfoInterceptor.getUserInfo().getUserId();
//            Object orderJson = orderOpt.get(userId);
//
//            if(!StringUtils.isEmpty(orderJson)){
//
//                return  new ResultVO(false,"不要重复下单");
//            }
//
//            //下单
//            MsOrder msOrder = new MsOrder();
//            msOrder.setSeckillUserId(userId);
//            msOrder.setCreatedate(new Date());
//            msOrder.setSeckillMoney(msGoods.getSeckillPrice());
//            msOrder.setUpdatedate(new Date());
//            msOrder.setSeckillGoodsId(msGoods.getSeckillId()+"");
//
//            orderOpt.put(userId,JSONUtil.toJsonStr(msOrder));
//
////        try {
////            Thread.sleep(2000);
////        } catch (InterruptedException e) {
////            e.printStackTrace();
////        }
//
//            //扣库存
//            msGoods.setSeckillRemaining(msGoods.getSeckillRemaining() - 1);
//            operations.put(msGoods.getSeckillId()+"",JSONUtil.toJsonStr(msGoods));
//
//
//            //todo 将订单信息存储到mysql（异步消息  rocketmq）
//
//            //释放锁
//            redisTemplate.delete("menhu:miaosha:lock");
//            return new ResultVO(true,"success");
//        } catch (Exception exception) {
//            exception.printStackTrace();
//            return new ResultVO(false,"发生错误");
//        } finally {
//
//        }
//    }

    @Autowired
    private RedissonClient redissonClient;


    @Override
    public ResultVO msOrder(String goodsId, String time) {

        String userId = "1";


         //setnx order:${goodsId}:${time} ?
        Boolean hasMideng =
                redisTemplate.boundValueOps("mideng:order:" + goodsId + ":" + time + ":" + userId).setIfAbsent("?");
        if(!hasMideng){//幂等
            return new ResultVO(false,"请勿重复操作!!!");
        }else{//没有幂等
            redisTemplate.expire("mideng:order:" + goodsId + ":" + time + ":" + userId,30,TimeUnit.SECONDS);
        }

//
//        //获取锁 setnx menhu:miaosha:lock ?
//        Boolean hasLock = redisTemplate.boundValueOps("menhu:miaosha:lock:"+goodsId).setIfAbsent("?");
////        if(!hasLock){  非阻塞锁
////            return new ResultVO(false,"系统繁忙");
////        }
//        while (!hasLock){//阻塞锁
//            hasLock = redisTemplate.boundValueOps("menhu:miaosha:lock").setIfAbsent("?");
//        }

//        redisTemplate.expire("menhu:miaosha:lock:"+goodsId,100,TimeUnit.MILLISECONDS);

        RLock lock = redissonClient.getLock("menhu:miaosha:lock:" + goodsId);//setnx lock ?


        try {

            //lock.lock(); //获取分布式锁（基于redis setnx命令实现） 阻塞锁

            lock.tryLock(10,10,TimeUnit.SECONDS);//非阻塞锁

            BoundHashOperations<String, Object, Object> operations = redisTemplate.boundHashOps("menhu:miaosha:goods:"+time);

            BoundHashOperations<String, Object, Object> orderOpt = redisTemplate.boundHashOps("menhu:miaosha:order:" + goodsId);


            Object goodsJson = operations.get(goodsId);

            if(StringUtils.isEmpty(goodsJson)){

                return  new ResultVO(false,"活动已经结束");
            }

            MsGoods msGoods = JSONUtil.toBean((String) goodsJson, MsGoods.class);

            Integer seckillRemaining = msGoods.getSeckillRemaining();  //5

            if (seckillRemaining < 1) {//1  1
                return  new ResultVO(false,"该商品已经卖完");
            }


            //判断用户是否已经购买了该商品
            //String userId = UUID.randomUUID().toString();  //UserInfoInterceptor.getUserInfo().getUserId();
            Object orderJson = orderOpt.get(userId);

            if(!StringUtils.isEmpty(orderJson)){
                return  new ResultVO(false,"不要重复下单");
            }

            //下单
            MsOrder msOrder = new MsOrder();
            msOrder.setSeckillUserId(userId);
            msOrder.setCreatedate(new Date());
            msOrder.setSeckillMoney(msGoods.getSeckillPrice());
            msOrder.setUpdatedate(new Date());
            msOrder.setSeckillGoodsId(msGoods.getSeckillId()+"");

            orderOpt.put(userId,JSONUtil.toJsonStr(msOrder));


            //扣库存
            msGoods.setSeckillRemaining(msGoods.getSeckillRemaining() - 1);
            operations.put(msGoods.getSeckillId()+"",JSONUtil.toJsonStr(msGoods));


            //todo 将订单信息存储到mysql（异步消息  rocketmq）

            return new ResultVO(true,"success");
        } catch (Exception exception) {
            exception.printStackTrace();
            return new ResultVO(false,"fail");
        } finally {
            //释放锁
            lock.unlock();
        }

    }
}
